'use client';

/* eslint jsx-a11y/click-events-have-key-events: warn */
import { useGateValue } from '@statsig/react-bindings';
import { useQuery } from '@tanstack/react-query';
import clsx from 'clsx';
import { usePathname } from 'next/navigation';
import React, { forwardRef, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { twMerge } from 'tailwind-merge';

import { useStores } from '@/app/(root)/AppProviders';
import AnimateCoverPill from '@/components/button/AnimateCoverPill';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { ClipLikeButton } from '@/components/button/ClipLikeButton';
import ClipCaption from '@/components/caption/ClipCaption';
import RemixContestComponent from '@/components/contest/RemixContestComponent';
import { AvatarMaskShape } from '@/components/image/Avatar';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import { SkeletonBone } from '@/components/layout/Skeleton';
import ProfileLink from '@/components/link/ProfileLink';
import PlaybarSyncVideoPlayer from '@/components/playbar/PlaybarSyncVideoPlayer';
import { SongMenuWithContext } from '@/components/song/newActions/SongMenuWithContext';
import AvatarTag from '@/components/tag/AvatarTag';
import { ModelNameTag } from '@/components/tag/ModelNameTag';
import SummaryOrFullTags from '@/components/tag/SummaryOrFullTags';
import Tag, { TagVariant } from '@/components/tag/Tag';
import { toast } from '@/components/toast/Toast';
import { Tooltip } from '@/components/tooltip/Tooltip';
import { ThemeMode, useThemeContext } from '@/context/ThemeContext';
import useBreakpoint, { useBreakpointMd } from '@/hooks/useBreakpoint';
import ContestClipContext, { useAllContestClips } from '@/hooks/useContestClip';
import {
  CommentIcon,
  MoreHorizontalIcon,
  PauseIcon,
  PlayIcon,
  PlusIcon,
  RemixIcon,
  ShareArrowIcon,
  SuccessIcon,
  ThumbsDownIcon,
  TrashIcon,
  UserAddIcon,
  UserAddedIcon,
  VideoIcon,
} from '@/icons';
import { useApiClient } from '@/lib/apiClient';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { Clip } from '@/state/clipStore';
import {
  ORIGINAL_IMAGE,
  REFERRER_PARAM,
  SIGNUP_SOURCE_PARAM,
  SIGNUP_SOURCE_VALUES,
  SMALL_IMAGE,
} from '@/utils/constants';
import { eventLogger } from '@/utils/event-logger';
import { ActionName } from '@/utils/event-names';
import { isStaff, isVideoGenerationFeatureEnabled } from '@/utils/session';
import {
  formatDateStringWTime,
  getClerkSignInRedirectProps,
  getCountString,
} from '@/utils/utils';

import ActiveListenersCount from './ActiveListenersCount';

export type Props = React.HTMLAttributes<HTMLDivElement> & {
  imageClassName?: string;
  contentClassName?: string;
  title?: string;
  avatarImageUrl?: string;
  handle?: string;
  displayName?: string;
  personaId?: string;
  personaDisplayName?: string;
  personaImageUrl?: string;
  personaUserAvatarImageUrl?: string;
  personaUserHandle?: string;
  personaUserDisplayName?: string;
  videoUrl?: string;
  imageUrl?: string;
  tags?: string[];
  caption?: string;
  createdAt?: string;
  clipType?: string;
  modelMajorVersion?: string;
  modelName?: string;
  playCount?: number | null;
  commentCount?: number | null;
  likeCount?: number | null;
  dislikeCount?: number | null;
  isFollowing?: boolean;
  isDisliked?: boolean;
  isCurrentSong?: boolean;
  isPlaying?: boolean;
  isTrashed?: boolean;
  isRemixBase?: boolean;
  onImageClick?: () => void;
  onFollowClick?: () => void;
  onPlayCountClick?: () => void;
  onCommentClick?: () => void;
  onDislikeClick?: () => void;
  onAddToPlaylistClick?: () => void;
  onShareClick?: () => void;
  onPlayClick?: () => void;
  onRemixClick?: () => void;
  onRemixContestClick?: ({
    isFromMobileButton,
  }: {
    isFromMobileButton: boolean;
  }) => void;
  onAnimateCoverClick?: () => void;
  titleContent?: React.ReactNode | React.ComponentType<{ children?: string }>;
  id?: string;
  isSongOwner?: boolean;
  clip: Clip;
};

const SongPageHeader = forwardRef<HTMLDivElement, Props>((props, ref) => {
  const {
    children,
    className,
    imageClassName,
    contentClassName,
    title,
    avatarImageUrl,
    handle,
    displayName,
    personaId,
    personaDisplayName,
    personaImageUrl,
    personaUserAvatarImageUrl,
    personaUserHandle,
    personaUserDisplayName,
    videoUrl,
    imageUrl,
    tags,
    caption,
    createdAt,
    clipType,
    modelMajorVersion,
    modelName,
    playCount,
    commentCount,
    likeCount,
    dislikeCount,
    isFollowing,
    isDisliked,
    isCurrentSong,
    isPlaying,
    isTrashed,
    isRemixBase,
    onImageClick,
    onFollowClick,
    onPlayCountClick,
    onCommentClick,
    onDislikeClick,
    onAddToPlaylistClick,
    onShareClick,
    onPlayClick,
    onRemixClick,
    onRemixContestClick,
    onAnimateCoverClick,
    titleContent,
    id,
    isSongOwner,
    clip,
    ...restProps
  } = props;

  const { t } = useTranslation();

  const isNotTiny = useBreakpoint(360);
  const isTablet = useBreakpointMd();
  const isMobile = !isTablet;
  const { session, apiClient } = useStores();
  const pathname = usePathname();
  const contestGate = useGateValue('contest-hub-song-pages');
  const contestClipContext = useContext(ContestClipContext);
  const { isActiveContestSubmission, isContestBaseClip } =
    contestClipContext || {};
  const { data: allContestsData } = useAllContestClips();
  const apiClientHook = useApiClient();
  const { effectiveTheme } = useThemeContext();
  // Get the base clip ID for contest submissions
  const baseClipId = (() => {
    if (!isActiveContestSubmission || !isActiveContestSubmission({ clip }))
      return null;

    const contestIds = clip.metadata?.contest_ids || [];
    if (contestIds.length === 0) return null;

    const relevantContest = allContestsData?.contests?.find((contest) =>
      contestIds.includes(contest.id)
    );

    return relevantContest?.base_clip_ids?.[0] || null;
  })();

  // Fetch the base clip data
  const { data: baseClip, isLoading: isLoadingBaseClip } = useQuery({
    queryKey: ['clip', baseClipId],
    queryFn: async () => {
      if (!baseClipId) return null;

      const { data } = await apiClientHook.GET('/api/clip/{clip_id}', {
        params: {
          path: { clip_id: baseClipId },
        },
      });

      return data || null;
    },
    enabled: !!baseClipId,
  });

  const badgeTheme =
    effectiveTheme === ThemeMode.Dark
      ? clip.metadata?.model_badges?.songrow?.dark
      : clip.metadata?.model_badges?.songrow?.light;

  return (
    <div
      className={twMerge(
        '@container flex flex-row items-start justify-stretch gap-4',
        className
      )}
      {...restProps}
      ref={ref}
    >
      <div
        className={twMerge(
          clsx(
            'relative aspect-2/3 w-[200px] shrink-0 overflow-hidden rounded-xl',
            'after:absolute after:inset-x-0 after:bottom-0 after:hidden after:h-1/6 after:bg-linear-to-t after:from-black',
            {
              'cursor-pointer': !!onImageClick,
              'max-md:h-[70vh]': !!videoUrl,
            }
          ),
          imageClassName
        )}
        onClick={clip.preview_seconds === undefined ? onImageClick : undefined}
      >
        {!imageUrl ? (
          <SkeletonBone className='block h-full w-full rounded-md' />
        ) : (
          <>
            <ImageWithFallback
              className='block h-full w-full cursor-pointer object-cover'
              alt='Song Cover Image'
              imageSize={ORIGINAL_IMAGE}
              src={imageUrl}
            />
            {videoUrl && (
              <div
                className={clsx('absolute inset-0', {
                  'max-md:hidden': !(isCurrentSong && isPlaying),
                })}
              >
                <PlaybarSyncVideoPlayer
                  className='pointer-events-none block h-full w-full object-cover'
                  videoUrl={videoUrl}
                  isCurrentSong={isCurrentSong}
                />
              </div>
            )}
            {onAnimateCoverClick &&
              session.userId &&
              session.userId === clip.user_id && (
                <AnimateCoverPill
                  clip={clip}
                  onClick={onAnimateCoverClick}
                  className='absolute bottom-2 left-1/2 -translate-x-1/2'
                />
              )}
          </>
        )}
      </div>
      <div
        className={twMerge(
          'relative flex flex-1 flex-col gap-2 self-stretch',
          contentClassName
        )}
      >
        {typeof titleContent === 'function'
          ? React.createElement(titleContent, {}, title)
          : titleContent || (
              <h1 className='font-serif text-[40px]/[56px] font-light text-foreground-primary'>
                {title}
              </h1>
            )}
        <div className='flex flex-row items-center justify-start gap-4'>
          <AvatarTag
            className='font-sans text-sm font-medium text-foreground-primary'
            displayName={displayName}
            handle={handle || ''}
            imageUrl={avatarImageUrl}
            imageSize={SMALL_IMAGE}
          />
          {onFollowClick && (
            <Button
              variant={ButtonVariant.Primary}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              active={isFollowing}
              icon={isFollowing ? UserAddedIcon : UserAddIcon}
              onClick={onFollowClick}
              className='w-26'
            >
              {isFollowing ? t('profile.following') : t('profile.follow')}
            </Button>
          )}
        </div>

        {personaId && (
          <AvatarTag
            className='font-sans text-sm font-medium text-foreground-primary'
            displayName={personaDisplayName}
            href={`/persona/${personaId}`}
            imageUrl={personaImageUrl}
            imageSize={SMALL_IMAGE}
            maskShape={AvatarMaskShape.Persona}
          >
            {personaUserHandle && (
              <>
                <ProfileLink
                  className='line-clamp-1 max-w-fit break-all'
                  href={`/persona/${personaId}`}
                >
                  {personaDisplayName}
                </ProfileLink>
                <div className='flex flex-row items-center justify-start gap-2 font-sans text-xs font-normal text-foreground-secondary'>
                  <div>By</div>
                  <AvatarTag
                    displayName={personaUserDisplayName}
                    handle={personaUserHandle}
                    imageUrl={personaUserAvatarImageUrl}
                    imageSize={SMALL_IMAGE}
                    avatarClassName='w-4 h-4'
                  />
                </div>
              </>
            )}
          </AvatarTag>
        )}
        {(clip?.metadata.tags ||
          clip?.metadata.negative_tags ||
          clip?.display_tags) && (
          <div className='my-2'>
            <SummaryOrFullTags
              tags={clip?.metadata.tags || undefined}
              negativeTags={clip?.metadata.negative_tags || undefined}
              displayTags={clip?.display_tags || undefined}
            />
          </div>
        )}
        <ClipCaption
          caption={caption}
          clipId={id}
          clip={clip}
          isSongOwner={isSongOwner}
        />
        <div className='flex flex-row items-center justify-start gap-2'>
          {createdAt && (
            <span
              className='text-sm text-foreground-secondary'
              title={formatDateStringWTime(createdAt)}
            >
              {formatDateStringWTime(createdAt)}
            </span>
          )}
          {clip.metadata?.type === 'studio_export' ? (
            <Tag variant={TagVariant.Studio}>Made with Studio</Tag>
          ) : null}
          <ModelNameTag
            clipType={clipType}
            modelMajorVersion={modelMajorVersion}
            modelName={modelName}
            displayName={clip.metadata?.model_badges?.songrow?.display_name}
            textColor={
              badgeTheme?.text_color ? `#${badgeTheme.text_color}` : undefined
            }
            backgroundColor={
              badgeTheme?.background_color
                ? `#${badgeTheme.background_color}`
                : undefined
            }
            borderColor={
              badgeTheme?.border_color
                ? `#${badgeTheme.border_color}`
                : undefined
            }
            previewClipType={
              clip.preview_seconds === undefined
                ? undefined
                : clip.preview_seconds === 0
                  ? 'lockedPreview'
                  : 'preview'
            }
          />
          {isActiveContestSubmission && isActiveContestSubmission({ clip }) ? (
            <Tooltip label='Submitted to Contest'>
              <div className='cursor-default'>
                <Tag className='mt-1 p-1'>
                  <SuccessIcon className='h-3.5 w-3.5' />
                </Tag>
              </div>
            </Tooltip>
          ) : null}
          {!isTrashed ? null : (
            <Tag className='mb-0'>
              <TrashIcon />
            </Tag>
          )}
        </div>
        {isRemixBase && onRemixClick && contestGate && (
          <div className='mt-2'>
            <Button
              variant={ButtonVariant.Aura}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              icon={RemixIcon}
              onClick={onRemixClick}
              className='bg-gradient-to-r from-accent-purple to-accent-pink font-medium text-white'
            >
              Remix
            </Button>
          </div>
        )}
        <div className='w-fit'>
          {isStaff(session) && id && <ActiveListenersCount clipId={id} />}
        </div>
        <div className='flex-1'>{children}</div>
        {isActiveContestSubmission &&
          isActiveContestSubmission({ clip }) &&
          isContestBaseClip &&
          !isContestBaseClip({ clipId: clip.id }) &&
          onRemixContestClick &&
          contestGate &&
          isMobile && (
            <div className='mb-4 w-full'>
              <RemixContestComponent
                baseClip={baseClip as Clip | null}
                isLoading={isLoadingBaseClip}
                onRemixClick={() => {
                  onRemixContestClick({ isFromMobileButton: true });
                }}
              />
            </div>
          )}
        <div className='flex flex-row flex-wrap items-end justify-between gap-3'>
          <div
            className={clsx(
              'flex flex-1 flex-row items-center justify-start gap-2',
              'max-md:w-full max-md:flex-wrap max-md:justify-center'
            )}
          >
            <Button
              className='grow md:grow-0'
              variant={ButtonVariant.Primary}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              active={false}
              icon={PlayIcon}
              iconClassName='mx-0'
              aspectSquare={false}
              href={undefined}
              onClick={onPlayCountClick}
              aria-label='Play Count'
            >
              {isNotTiny &&
                playCount != null &&
                getCountString(playCount, true)}
            </Button>
            <Button
              className='grow md:grow-0'
              variant={ButtonVariant.Primary}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              active={false}
              icon={CommentIcon}
              iconClassName='mx-0'
              aspectSquare={false}
              href={undefined}
              onClick={onCommentClick}
              disabled={clip.preview_seconds !== undefined}
            >
              {isNotTiny &&
                commentCount != null &&
                getCountString(commentCount, true)}
            </Button>
            <ClipLikeButton
              clipId={clip.id}
              className='grow md:grow-0'
              variant={ButtonVariant.Primary}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              iconClassName='mx-0'
              aspectSquare={false}
              href={undefined}
              showCount={isNotTiny && likeCount != null}
              hideCountIfZero
              onClick={({ isLiked }) => {
                logWebUserEvent({
                  actionName: 'LikeSongOnSongPageClicked',
                  context: {
                    clipId: clip.id,
                    version: 'v1',
                  },
                });
                eventLogger.logAudioActionEvent(
                  !isTablet,
                  isLiked ? ActionName.undoLikeSong : ActionName.likeSong,
                  clip,
                  session,
                  pathname
                );
              }}
              clerkRedirectProps={() => {
                logWebUserEvent({
                  actionName: 'LikeSongOnSongPageClicked',
                  context: {
                    clipId: clip.id,
                    version: 'v1',
                  },
                });
                return getClerkSignInRedirectProps(`/song/${clip.id}`, {
                  [REFERRER_PARAM]: pathname,
                  [SIGNUP_SOURCE_PARAM]: SIGNUP_SOURCE_VALUES.SONG_PAGE,
                });
              }}
              disabled={clip.preview_seconds !== undefined}
            />
            <Button
              className='grow md:grow-0'
              variant={ButtonVariant.Primary}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              active={isDisliked || false}
              icon={ThumbsDownIcon}
              iconClassName='mx-0'
              aspectSquare={false}
              href={undefined}
              onClick={onDislikeClick}
              disabled={clip.preview_seconds !== undefined}
            >
              {isNotTiny && dislikeCount && getCountString(dislikeCount)}
            </Button>
            {isVideoGenerationFeatureEnabled(session) && (
              <Button
                className='grow md:grow-0'
                variant={ButtonVariant.Primary}
                size={ButtonSize.Mini}
                shape={ButtonShape.Pill}
                active={false}
                icon={VideoIcon}
                iconClassName='mx-0'
                aspectSquare={false}
                href={undefined}
                onClick={async () => {
                  if (id) {
                    toast({
                      title: 'Video gen started',
                      status: 'info',
                      duration: 3000,
                      isClosable: true,
                    });
                    await apiClient.POST('/api/video_gen/generate_video', {
                      body: {
                        clip_id: id,
                      },
                    });
                    toast({
                      title:
                        'Video gen will be ready in a few minutes, check back soon!',
                      status: 'info',
                      duration: 3000,
                      isClosable: true,
                    });
                  }
                }}
                disabled={clip.preview_seconds !== undefined}
              >
                {isNotTiny && dislikeCount && getCountString(dislikeCount)}
              </Button>
            )}
            <SongMenuWithContext
              clip={clip}
              className='grow md:grow-0'
              shape={ButtonShape.Pill}
              size={ButtonSize.Mini}
              aspectSquare={false}
              icon={MoreHorizontalIcon}
              variant={ButtonVariant.Primary}
              active={false}
              iconClassName='mx-0'
              aria-label='More Options'
            />
          </div>
          <div
            className={clsx(
              'flex flex-row items-center justify-end gap-2',
              'max-md:w-full max-md:justify-center'
            )}
          >
            <Button
              className='grow max-md:px-4 md:grow-0'
              variant={ButtonVariant.Standard}
              size={isTablet ? ButtonSize.Small : ButtonSize.Large}
              shape={ButtonShape.Rounded}
              icon={PlusIcon}
              aspectSquare={false}
              href={undefined}
              onClick={onAddToPlaylistClick}
              title={t('songActions.addToPlaylist')}
              disabled={clip.preview_seconds !== undefined}
            />
            <Button
              className='grow max-md:px-4 md:grow-0'
              variant={ButtonVariant.Standard}
              size={isTablet ? ButtonSize.Small : ButtonSize.Large}
              shape={ButtonShape.Rounded}
              icon={ShareArrowIcon}
              aspectSquare={false}
              href={undefined}
              onClick={onShareClick}
            />
            <Button
              className='grow max-md:px-4 md:grow-0'
              variant={ButtonVariant.Primary}
              size={isTablet ? ButtonSize.Small : ButtonSize.Large}
              shape={ButtonShape.Rounded}
              aspectSquare={false}
              icon={isPlaying ? PauseIcon : PlayIcon}
              href={undefined}
              onClick={onPlayClick}
            />
          </div>
        </div>
      </div>
    </div>
  );
});
SongPageHeader.displayName = 'SongPageHeader';

export default SongPageHeader;
